package com.squirrels.server.utils;

import com.squirrels.server.annotation.NettyServerWorker;
import com.squirrels.server.config.ServerConfig;
import com.squirrels.server.work.ServerWorker;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

/**
 * 创建者: FlyingSquirrels
 * 创建时间: 2024/7/29 15:04
 * 描述:
 */
public class SystemUtils {

    private static SystemUtils systemUtils;

    private SystemUtils(){}

    /**
     * 获取工具类
     * @return
     */
    public synchronized static SystemUtils getUtils(){
        if (systemUtils == null) {
            return new SystemUtils();
        }
        return systemUtils;
    }

    /**
     * 读取配置文件名
     * @return
     * @throws IOException
     */
    public String[] readConfigNames() throws IOException {
        List<String> configNameList = new ArrayList<>();
        // 使用ResourcePatternResolver扫描Resource文件夹下的所有yaml文件
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources(ServerConfig.configPath);
        for (Resource resource : resources) {
            System.out.println(resource.getURL());
            if (matchString(resource.getFilename(),".yml")) {
                String originConfigName = resource.getFilename();
                originConfigName = originConfigName.replaceAll("application-","");
                originConfigName = originConfigName.replaceAll(".yml","");
                configNameList.add(originConfigName);
            }
        }
        String[] configNames = configNameList.toArray(new String[]{});
        return  configNames;
    }

    /**
     * 读取所有Worker类
     * @return
     * @throws IOException
     */
    public ConcurrentHashMap<String,ServerWorker> readWorkers() throws Exception {
        // 没有注解忽略的类
        int ignoreClass=0;
        // 路由集合
        ConcurrentHashMap<String,ServerWorker> routerMap = new ConcurrentHashMap<>();
        // 资源列表
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 遍历资源
        Resource[] resources = resolver.getResources(ServerConfig.workerPath);
        for (Resource resource : resources) {
            // 过滤出是class文件
            if (matchString(resource.getFilename(),".class")) {
                String className = ServerConfig.workerPackage + "." + resource.getFilename().replace(".class","");
                Class<ServerWorker> workerClass = (Class<ServerWorker>) Class.forName(className);
                // 检查是否非class
                int modifiers = workerClass.getModifiers();
                if (Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers)) {
                    continue;
                }
                // 根据注解创建对象
                ServerWorker serverWorker = workerClass.getConstructor().newInstance();
                NettyServerWorker annotation = serverWorker.getClass().getAnnotation(NettyServerWorker.class);
                if (null == annotation){
                    ignoreClass++;
                    continue;
                }
                String routerKey = annotation.value();
                if (null != routerMap.get(routerKey)){
                    throw new Exception("重复的路由 类路径: 'com.squirrels.server.work'");
                }
                routerMap.put(routerKey,serverWorker);
            }
        }
        if(ignoreClass != 0) {
            System.out.println("警告: 有 "+ignoreClass+" 个类被忽略了,请检查 '" +
                    ServerConfig.workerPath +"' 路径下的类" +
                    ",确保正确添加了注解 '@NettyServerWorker(\"{var}\")'");
        }
        return  routerMap;
    }

    /**
     * 字符串中是否含有match
     * @param name,match
     * @return
     */
    public boolean matchString(String name,String match) {
        String pattern = ".*" + match + ".*";
        return Pattern.matches(pattern, name);
    }
}